/*
 * Copyright 2011 Biz-e (info@biz-e.nl)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.bize.knexions.android.knexion;

import java.nio.charset.MalformedInputException;
import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.util.Log;

/**
 * General DataAccess object for managing SQLite access.
 * 
 * @author Joost A. Bloemsma
 */
public class DataStorage {
	private static final String TAG = "DataStorage";
    private KnexionAccountOpenHelper dbHelper;
    private static final String FIELD_ID = "id";
    private static final String FIELD_CTX = "context";
	private static final String FIELD_NAME = "name";
	private static final String FIELD_DATA = "data";
	private static final String TABLE_NAME = "knexiondata";
	
    /**
     * Constructs a new DataStorage instance
     * @param context
     */
    public DataStorage(Context context) {
    	super();
    	dbHelper = new KnexionAccountOpenHelper(context);
    }
	/**
	 * @param object
	 * @return true if storage succeeded
	 */
	public boolean storeObject(Storable object) {
		return store(object.getContext(),object.getName(), object.getData());
	}
	
	/**
	 * Returns a list of all keys (names) for a specified context.
	 * @param context
	 * @return A {@link List<String>} of names
	 */
	public List<String> getAllNames(String context) {
		ArrayList<String> names = new ArrayList<String>();
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		qb.setTables(TABLE_NAME);
		SQLiteDatabase db = dbHelper.getReadableDatabase();
		Cursor c = qb.query(db,null, FIELD_CTX + " = ?", new String[] {context}, null, null, FIELD_NAME);
		
		while (c.moveToNext()) {
			names.add(c.getString(c.getColumnIndex(FIELD_NAME)));
		}
		db.close();
		return names;
	}
	
	/**
	 * @param s
	 * @return true if the data is found
	 */
	public boolean fillStorable(Storable s) {
		if (s == null) return false;
		String data = getData(s.getContext(), s.getName());
		try {
			s.setData(data);
		} catch (MalformedInputException e) {
			return false;
		}
		return true;
	}
	
	private boolean store(String context, String name, String data) {
		boolean success = false;
		boolean exists = dataExists(context, name); 
		ContentValues cv = new ContentValues();
		cv.put(FIELD_CTX, context);
		cv.put(FIELD_DATA, data);
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		if (!exists) {
			cv.put(FIELD_NAME,name);
			success = db.insert(TABLE_NAME, null, cv) >= 0; 
		} else {
			success = db.update(TABLE_NAME, cv, FIELD_CTX + " = ? AND " + FIELD_NAME + " = ?", new String[] {context,name}) > 0;
		}
		db.close();
		return success;
	}
	
	private String getData(String context, String name) {
		String data = null;
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		qb.setTables(TABLE_NAME);
		SQLiteDatabase db = dbHelper.getReadableDatabase();
		Cursor c = qb.query(db,null, FIELD_CTX + " = ? AND " + FIELD_NAME + " = ?", new String[] {context,name}, null, null, null);
		if (c.getCount() > 0) {
			c.moveToFirst();
			data = c.getString(c.getColumnIndex(FIELD_DATA));
		}
		db.close();
		return data;
	}
	
	private boolean dataExists(String context, String name) {
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		qb.setTables(TABLE_NAME);
		SQLiteDatabase db = dbHelper.getReadableDatabase();
		Cursor c = qb.query(db,null, FIELD_CTX + " = ? AND " + FIELD_NAME + " = ?", new String[] {context,name}, null, null, null);
		db.close();
		return c.getCount() > 0;
	}
	
	private class KnexionAccountOpenHelper extends SQLiteOpenHelper {
		private static final int DATABASE_VERSION = 3;
		private static final String DATABASE_NAME = "Knexions.db";
		
	    private static final String DICTIONARY_TABLE_CREATE =
	                "CREATE TABLE " + TABLE_NAME + " (" +
	                 FIELD_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
	                 FIELD_CTX + " TEXT NOT NULL, " +
	                 FIELD_NAME + " TEXT NOT NULL, " +
	                 FIELD_DATA + " TEXT);";
		
	    public KnexionAccountOpenHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}
		
		@Override
		public void onCreate(SQLiteDatabase db) {
			try {
				db.execSQL(DICTIONARY_TABLE_CREATE);
				db.close();
			} catch (SQLiteException e) {
				System.out.println(e);
			}
		}
		
		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
	                + newVersion + ", which will destroy all old data");

	        // Kills the table and existing data
	        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);

	        // Recreates the database with a new version
	        onCreate(db);
		}
		
	}
	
}
